<template>
  <div ref="canvas">
  </div>
</template>

<script lang="ts" setup>
import {onMounted, ref} from "vue";
// 引入 three js
import * as THREE from "three"
// 引入扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入扩展库GLTFLoader.js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

// 扩展库引入——旧版本，比如122, 新版本路径addons替换了examples/jsm
// import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

// 有一个场景 scene，还需要有个模型Mesh(Mesh模型 - 由对象Geometry，材质material组成)
// 通过 scene 的 add 方法将 Mesh模型 添加到场景中
// 然后通过 渲染器WebGLRenderer 使用 相机camera 把这个场景scene 拍下来，然后展示到页面上

const canvas = ref<any>(null);

// 创建3D场景对象Scene - 虚拟的3D场景，用来表示模拟生活中的真实三维场景,或者说三维世界
const scene = new THREE.Scene();

// 创建一个长方体几何对象Geometry - 几何体API，用来表示三维物体的几何形状。
const geometry = new THREE.BoxGeometry(100, 60, 20);
//创建一个材质对象Material - 物体的外观效果，比如颜色，就需要通过材质Material相关的API实现。
const material = new THREE.MeshBasicMaterial({
  color: 0x0000ff, //设置材质颜色
  transparent:true,//开启透明
  opacity:0.5,//设置透明度
});
// 网格模型对象Mesh - threejs中可以通过网格模型Mesh表示一个虚拟的物体，比如一个箱子、一个鼠标
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material);
// 通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置，默认是坐标原点
mesh.position.set(100,0,0);
// 通过.add()方法，把网格模型mesh添加到三维场景scene中
scene.add(mesh);

// ThreeJs 如果想把三维场景Scene渲染到web网页上，还需要定义一个虚拟相机Camera
// ThreeJs 提供了正投影相机OrthographicCamera 和 透视投影相机PerspectiveCamera

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
// 通过位置属性.position可以设置相机的位置 - 相机在Three.js三维坐标系中的位置
camera.position.set(-800, 500, 800);
// 设置.lookAt()方法的参数，指定一个3D坐标，来观察这个目标
// 指向mesh对应的位置
// camera.lookAt(mesh.position);
camera.lookAt(0, 0, 0);
// 透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间，被称为视锥体
//   1. fov	相机视锥体竖直方向视野角度	50
//   2. aspect	相机视锥体水平方向和竖直方向长度比，一般设置为Canvas画布宽高比width / height	1
//   3. near	相机视锥体近裁截面相对相机距离	0.1
//   4. far	相机视锥体远裁截面相对相机距离，far-near构成了视锥体高度方向	2000
// 只有视锥体之内的物体，才会渲染出来，视锥体范围之外的物体不会显示在Canvas画布上。
// const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

// AxesHelper：辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(300);
scene.add(axesHelper);

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 定义输出画布的尺寸(单位:像素px)
const width = 1000;
const height = 800;
// 设置three.js渲染区域的尺寸(像素px)
renderer.setSize(width, height);
// 执行渲染操作
renderer.render(scene, camera);

// 动画
const animate = () => {
  if (mesh) {
    requestAnimationFrame(animate.bind(this));
    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.01;
    renderer.render(scene, camera);
  }
}

onMounted(() => {
  // 将Canvas画布插入到HTML元素中
  canvas.value.appendChild(renderer.domElement);
  animate();
});

</script>
